package com.mt.api.modules.service.impl;


import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.mt.common.response.WebPageResponse;
import com.mt.common.response.WebResponse;
import com.mt.common.response.WebResponseUtils;
import com.mt.api.constants.enums.ProductStatusEnum;
import com.mt.api.modules.domain.*;
import com.mt.api.modules.domain.bo.ProductStatPageBo;
import com.mt.api.modules.domain.dto.*;
import com.mt.api.modules.domain.vo.*;
import com.mt.api.modules.manager.*;
import com.mt.api.modules.mapstruct.ProductDetailMapStruct;
import com.mt.api.modules.mapstruct.ProductMapStruct;
import com.mt.api.modules.service.IProductService;
import com.mt.api.util.AmountUtil;
import com.mt.api.util.SequenceBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: plover
 * @Date: 2022-05-06
 * @Description:
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ProductServiceImpl implements IProductService {

    private final IProductManager productManager;
    private final IProductDetailManager productDetailManager;
    private final ISkuManager skuManager;
    private final ICargoManager cargoManager;
    private final IInstoreManager instoreManager;

    private final ProductMapStruct productMapStruct;
    private final ProductDetailMapStruct productDetailMapStruct;


    @Override
    public WebResponse addProduct(AppProductAddBo bo) {
        Date now = new Date();
        List<AppProductAddBo.ProductDetail> productDetailList = bo.getProductDetails();
        int totalQty = productDetailList.stream().flatMap(productDetail -> productDetail.getSkuInfoList().stream())
                .filter(simpleSkuInfo -> Objects.nonNull(simpleSkuInfo.getQty()))
                .mapToInt(AppProductAddBo.SimpleSkuInfo::getQty).sum();

        List<Integer> skuIds = productDetailList.stream().flatMap(detail -> detail.getSkuInfoList().stream())
                .filter(simpleSkuInfo -> Objects.nonNull(simpleSkuInfo.getQty()))
                .map(AppProductAddBo.SimpleSkuInfo::getSkuId).collect(Collectors.toList());
        List<AppSku> skuList = skuManager.listByIds(skuIds);

        //生产单保存
        SequenceBuilder builder = new SequenceBuilder();
        String productNo = builder.builderProductNo();
        Product product = new Product();
        product.setProductNo(productNo);
        product.setProductTime(now);
        product.setRemark(bo.getRemark());
        product.setQty(totalQty);
        productManager.save(product);

        for (AppProductAddBo.ProductDetail productDetail : productDetailList) {
            if (Objects.isNull(productDetail.getCargoId())) {
                continue;
            }
            List<AppProductAddBo.SimpleSkuInfo> skuInfoList = productDetail.getSkuInfoList();
            for (AppProductAddBo.SimpleSkuInfo simpleSkuInfo : skuInfoList) {

                Integer qty = simpleSkuInfo.getQty();
                Integer skuId = simpleSkuInfo.getSkuId();
                if (Objects.isNull(qty) || qty == 0) {
                    continue;
                }
                Optional<AppSku> skuOptional = skuList.stream().filter(sku -> Objects.equals(sku.getId(), skuId)).findFirst();
                if (!skuOptional.isPresent()) {
                    continue;
                }
                AppSku sku = skuOptional.get();

                ProductDetail svProductDetail = new ProductDetail();
                svProductDetail.setProductId(product.getId());
                svProductDetail.setCargoNo(sku.getCargoNo());
                svProductDetail.setCargoId(sku.getCargoId());
                svProductDetail.setSkuId(skuId);
                svProductDetail.setSkuCode(sku.getSkuCode());
                svProductDetail.setColor(sku.getColor());
                svProductDetail.setSize(sku.getSize());
                svProductDetail.setQty(qty);
                productDetailManager.save(svProductDetail);
            }
        }
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse editProduct(AppProductAddBo bo) {
        Product product = productManager.getById(bo.getId());
        if (Objects.isNull(product)) {
            return WebResponseUtils.error("采购单不存在");
        }

        List<ProductDetail> dbProductDetailList = productDetailManager.getListByProductIds(Arrays.asList(bo.getId()));
        List<AppProductAddBo.ProductDetail> productDetailList = bo.getProductDetails();

        if (CollectionUtils.isEmpty(productDetailList)) {
            return WebResponseUtils.success();
        }

        //获取所有的sku
        List<Integer> skuIds = productDetailList.stream().flatMap(detail -> detail.getSkuInfoList().stream())
                .filter(simpleSkuInfo -> Objects.nonNull(simpleSkuInfo.getQty()))
                .map(simpleSkuInfo -> simpleSkuInfo.getSkuId()).collect(Collectors.toList());
        List<AppSku> skuList = skuManager.listByIds(skuIds);

        List<ProductDetail> addProductDetailList = Lists.newArrayList();
        List<ProductDetail> updateProductDetailList = Lists.newArrayList();
        for (AppProductAddBo.ProductDetail productDetail : productDetailList) {
            if (Objects.isNull(productDetail.getCargoId())) {
                continue;
            }

            for (AppProductAddBo.SimpleSkuInfo simpleSkuInfo : productDetail.getSkuInfoList()) {
                Integer qty = simpleSkuInfo.getQty();
                Integer skuId = simpleSkuInfo.getSkuId();
                if (Objects.isNull(qty) || qty == 0) {
                    continue;
                }
                Optional<AppSku> skuOptional = skuList.stream().filter(sku -> Objects.equals(sku.getId(), skuId)).findFirst();
                if (!skuOptional.isPresent()) {
                    continue;
                }
                AppSku sku = skuOptional.get();
                if (Objects.isNull(simpleSkuInfo.getId())) {
                    // 明细主键id不存在，则新增
                    ProductDetail svProductDetail = new ProductDetail();
                    svProductDetail.setProductId(product.getId());
                    svProductDetail.setCargoNo(sku.getCargoNo());
                    svProductDetail.setCargoId(sku.getCargoId());
                    svProductDetail.setSkuId(skuId);
                    svProductDetail.setSkuCode(sku.getSkuCode());
                    svProductDetail.setColor(sku.getColor());
                    svProductDetail.setSize(sku.getSize());
                    svProductDetail.setQty(qty);
                    addProductDetailList.add(svProductDetail);
                } else {
                    ProductDetail upProductDetail = new ProductDetail();
                    upProductDetail.setId(simpleSkuInfo.getId());
                    upProductDetail.setQty(simpleSkuInfo.getQty());
                    updateProductDetailList.add(upProductDetail);
                    //如果订单明细存在，则删除此明细
                    dbProductDetailList = dbProductDetailList.stream().filter(detail -> !Objects.equals(detail.getId(), simpleSkuInfo.getId())).collect(Collectors.toList());
                }
            }
        }

        int addTotalQty = addProductDetailList.stream().mapToInt(ProductDetail::getQty).sum();
        int updateTotalQty = updateProductDetailList.stream().mapToInt(ProductDetail::getQty).sum();
        //采购单主表
        Product upProduct = new Product();
        upProduct.setId(product.getId());
        upProduct.setRemark(bo.getRemark());
        upProduct.setQty(addTotalQty + updateTotalQty);
        productManager.updateById(upProduct);

        if (CollectionUtils.isNotEmpty(addProductDetailList)) {
            productDetailManager.saveBatch(addProductDetailList);
        }
        if (CollectionUtils.isNotEmpty(updateProductDetailList)) {
            productDetailManager.updateBatchById(updateProductDetailList);
        }
        if (CollectionUtils.isNotEmpty(dbProductDetailList)) {
            List<Integer> removeIds = dbProductDetailList.stream().map(ProductDetail::getId).collect(Collectors.toList());
            productDetailManager.removeByIds(removeIds);
        }
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse<ProductInfoVo> productDetail(Integer productId) {
        Product product = productManager.getById(productId);
        if (Objects.isNull(product)) {
            return WebResponseUtils.error("采购单不存在");
        }
        ProductVo productVo = productMapStruct.toVo(product);
        //采购明细
        List<ProductDetail> productDetailList = productDetailManager.getListByProductId(productId);
        List<ProductDetailSimpleVo> productDetailSimpleVoList = productDetailMapStruct.toVoList(productDetailList);
        productDetailSimpleVoList = productDetailSimpleVoList.stream().sorted(Comparator.comparing(ProductDetailSimpleVo::getCargoNo)).collect(Collectors.toList());
        ProductInfoVo result = new ProductInfoVo();
        result.setProduct(productVo);
        result.setProductDetailList(productDetailSimpleVoList);
        return WebResponseUtils.success(result);
    }

    @Override
    public WebResponse cancelProduct(Integer productId) {
        Product product = productManager.getById(productId);
        if (Objects.isNull(product)) {
            return WebResponseUtils.error("采购单不存在");
        }
        Product upProduct = new Product();
        upProduct.setId(productId);
        upProduct.setStatus(ProductStatusEnum.CANCEL.getCode());
        productManager.updateById(upProduct);
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse<ProductDetailVo> getProductDetail(Integer productId) {
        Product product = productManager.getById(productId);
        if (Objects.isNull(product)) {
            return WebResponseUtils.error("采购单不存在");
        }
        ProductDetailVo vo = new ProductDetailVo();
        ProductVo productVo = productMapStruct.toVo(product);
        vo.setProduct(productVo);

        List<ProductDetail> productDetailList = productDetailManager.getListByProductId(productId);

        List<ProductDetailVo.Detail> detailList = Lists.newArrayList();

        List<Integer> cargoIds = productDetailList.stream().map(ProductDetail::getCargoId).distinct().collect(Collectors.toList());
        List<AppCargo> cargoList = CollectionUtils.isEmpty(cargoIds) ? Lists.newArrayList() : cargoManager.listByIds(cargoIds);

        Map<Integer, List<ProductDetail>> cargoMap = productDetailList.stream().collect(Collectors.groupingBy(ProductDetail::getCargoId));
        cargoMap.forEach((cargoId, productDetails) -> {
            ProductDetailVo.Detail detailVo = new ProductDetailVo.Detail();
            detailVo.setCargoId(cargoId);

            Optional<AppCargo> cargoOptional = cargoList.stream().filter(o -> Objects.equals(o.getId(), cargoId)).findFirst();
            if (cargoOptional.isPresent()) {
                AppCargo appCargo = cargoOptional.get();
                detailVo.setCargoNo(appCargo.getCargoNo());
                detailVo.setCargoName(appCargo.getRemark());
                detailVo.setPicUrl(appCargo.getPicUrl());
            }
            List<ProductDetailVo.SkuInfo> skuInfoList = productDetails.stream().map(detail -> {
                ProductDetailVo.SkuInfo skuInfo = new ProductDetailVo.SkuInfo();
                skuInfo.setId(detail.getId());
                skuInfo.setSkuId(detail.getSkuId());
                skuInfo.setQty(detail.getQty());
                skuInfo.setColor(detail.getColor());
                skuInfo.setSize(detail.getSize());
                return skuInfo;
            }).collect(Collectors.toList());
            detailVo.setSkuInfoList(skuInfoList);
            detailList.add(detailVo);
        });
        List<ProductDetailVo.Detail> details = detailList.stream().sorted(Comparator.comparing(ProductDetailVo.Detail::getCargoNo)).collect(Collectors.toList());
        vo.setDetailList(details);
        return WebResponseUtils.success(vo);
    }

    @Override
    public WebPageResponse<ProductStatByProductNoVo> statByProductNo(ProductStatPageBo bo) {
        Page page = productManager.statByProductNo(bo);
        List<ProductStatByProductNoDto> records = page.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return WebResponseUtils.successPageV2(page);
        }

        List<Integer> productIds = records.stream().map(ProductStatByProductNoDto::getId).collect(Collectors.toList());
        //查询所有的生产详情
        List<ProductDetail> productDetailList = productDetailManager.getListByProductIds(productIds);
        List<Integer> cargoIds = productDetailList.stream().map(ProductDetail::getCargoId).distinct().collect(Collectors.toList());
        //查询所有的款号信息
        List<AppCargo> cargoList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(cargoIds)) {
            cargoList = cargoManager.listByIds(cargoIds);
        }
        List<ProductStatByProductNoVo> result = Lists.newArrayList();
        for (ProductStatByProductNoDto record : records) {
            ProductStatByProductNoVo vo = new ProductStatByProductNoVo();
            String productNo = record.getProductNo();
            vo.setId(record.getId());
            vo.setProductNo(productNo);
            vo.setProductTime(DateUtil.formatDateTime(record.getProductTime()));
            vo.setCreator(record.getCreator());
            vo.setQty(record.getQty());
            vo.setStatus(record.getStatus());
            ProductStatusEnum statusEnum = ProductStatusEnum.ofCode(record.getStatus());
            if (Objects.nonNull(ProductStatusEnum.ofCode(record.getStatus()))) {
                vo.setStatusText(statusEnum.getName());
            }
            List<ProductDetail> filterProductDetailList = productDetailList.stream().filter(productDetail -> Objects.equals(productDetail.getProductId(), record.getId())).collect(Collectors.toList());

            BigDecimal totalAmount = BigDecimal.ZERO;
            List<ProductStatByProductNoVo.Detail> detailList = Lists.newArrayList();
            for (ProductDetail productDetail : filterProductDetailList) {
                ProductStatByProductNoVo.Detail detail = new ProductStatByProductNoVo.Detail();
                Optional<AppCargo> cargoOptional = cargoList.stream().filter(cargo -> Objects.equals(cargo.getId(), productDetail.getCargoId())).findFirst();
                if (cargoOptional.isPresent()) {
                    AppCargo cargo = cargoOptional.get();
                    detail.setAmount(AmountUtil.divideHundred(cargo.getPurchasePrice() * productDetail.getQty()));
                }
                totalAmount = totalAmount.add(new BigDecimal(detail.getAmount()));
                detail.setCargoNo(productDetail.getCargoNo());
                detail.setColor(productDetail.getColor());
                detail.setSize(productDetail.getSize());
                detail.setQty(productDetail.getQty());
                detailList.add(detail);
            }
            vo.setDetailList(detailList);
            vo.setAmount(totalAmount.toString());
            result.add(vo);
        }
        page.setRecords(result);
        return WebResponseUtils.successPageV2(page);
    }

}
